<?php
define('TOLERANCIA_SALIDA',     60);
define('TOLERANCIA_PORCENTAJE', 0.25);

class AlertasModel extends CustomModel
{

    public function getViajeFinalizado($idViaje)
    {
        $viajesAbm = new ABM('viajes');
        $joins = array(
            'conductores' => array('viajes.fkconductor' => 'conductores.idconductor'),
            'vehiculos'   => array('viajes.fkvehiculo'  => 'vehiculos.idvehiculo'),
            'grupos'      => array('viajes.fkgrupo'     => 'grupos.idgrupo'),
            'rutas'       => array('viajes.fkruta'      => 'rutas.idruta'),
        );
        $viaje = $viajesAbm->getWithJoin(array('idviaje' => $idViaje, 'status' => STATUS_OFFLINE), $joins);
        if ($viaje)
        {
            $viaje = $viaje[$idViaje];
            $viaje['diferencia_llegada'] = ((($viaje['llegada_real_timestamp'] - $viaje['llegada_estimada_timestamp']) > 0)?'+':'-').gmdate('H:i:s', abs($viaje['llegada_real_timestamp'] - $viaje['llegada_estimada_timestamp']));
            $viaje['salida']             = date('d/m/Y H:i:s', $viaje['salida_timestamp']);
            $viaje['salida_real']        = date('d/m/Y H:i:s', $viaje['salida_real_timestamp']);
            $viaje['llegada_estimada']   = date('d/m/Y H:i:s', $viaje['llegada_estimada_timestamp']);
            $viaje['llegada_real']       = date('d/m/Y H:i:s', $viaje['llegada_real_timestamp']);
            return $viaje;
        }
        else
        {
            return false;
        }
    }

    public function getViajesPorVehiculo($idVehiculo, $fechaDesde, $fechaHasta, $pageNumber)
    {
        return $this->getViajes($fechaDesde, $fechaHasta, $pageNumber, 'fkvehiculo', $idVehiculo);
    }

    public function getViajesPorGrupo($idGrupo, $fechaDesde, $fechaHasta, $pageNumber)
    {
        return $this->getViajes($fechaDesde, $fechaHasta, $pageNumber, 'fkgrupo', $idGrupo);
    }

    public function getViajesGenerales($fechaDesde, $fechaHasta, $pageNumber)
    {
        return $this->getViajes($fechaDesde, $fechaHasta, $pageNumber);
    }

    private function getViajes($desde, $hasta, $pageNumber, $porCampo = false, $valorCampo = false)
    {
        $viajesAbm = new ABM('viajes');
        $joins = array(
            'conductores' => array('viajes.fkconductor' => 'conductores.idconductor'),
            'vehiculos'   => array('viajes.fkvehiculo'  => 'vehiculos.idvehiculo'),
            'grupos'      => array('viajes.fkgrupo'     => 'grupos.idgrupo'),
            'rutas'       => array('viajes.fkruta'      => 'rutas.idruta'),
        );
        $filter   = filter('status', '=', STATUS_OFFLINE);
        $dateFrom = filter('salida_real_timestamp', '>=', $desde);
        $dateTo   = filter('salida_real_timestamp', '<=', $hasta);
        $date     = filter($dateFrom, 'AND', $dateTo);
        $filter   = filter($filter, 'AND', $date);
        if (!empty($porCampo) && (!empty($valorCampo)))
        {
            $filterAux = filter ($porCampo, '=', $valorCampo);
            $filter = filter($filter, 'AND', $filterAux);
        }
        $viajes = $viajesAbm->getPaginatedWithJoin($pageNumber, $filter, $joins, 20, 'salida_timestamp ASC', true);
        if ($viajes)
        {
            foreach ($viajes['results'] as &$viaje)
            {
                $viaje['diferencia_llegada'] = ((($viaje['llegada_real_timestamp'] - $viaje['llegada_estimada_timestamp']) > 0)?'+':'-').gmdate('H:i:s', abs($viaje['llegada_real_timestamp'] - $viaje['llegada_estimada_timestamp']));
                $viaje['salida']             = date('d/m/Y H:i:s', $viaje['salida_timestamp']);
                $viaje['salida_real']        = date('d/m/Y H:i:s', $viaje['salida_real_timestamp']);
                $viaje['llegada_estimada']   = date('d/m/Y H:i:s', $viaje['llegada_estimada_timestamp']);
                $viaje['llegada_real']       = date('d/m/Y H:i:s', $viaje['llegada_real_timestamp']);
                $viaje['historial']          = $this->getHistorial($viaje['idviaje'], $viaje['fkruta'], $viaje['salida_real_timestamp'], $viaje['salida_timestamp']);
            }
            return $viajes;
        }
        else
        {
            return false;
        }
    }

    public function getHistorial($idViaje, $idRuta, $fechaSalida, $salidaEsperada)
    {
        $puntosPorRutaAbm = new ABM('puntos_por_ruta');
        $join = array(
            'geolocalizaciones' => array(
                'type' => 'LEFT',
                'on'   => array(
                    'geolocalizaciones.fkpunto_por_ruta' => 'puntos_por_ruta.idpunto_por_ruta',
                    'geolocalizaciones.fkviaje'          => $idViaje,
                )
            )
        );
        $puntosPorRuta = $puntosPorRutaAbm->getWithJoin(array('fkruta' => $idRuta), $join, array('fkpunto_por_ruta ASC'));
        if (!empty($puntosPorRuta))
        {
            // Get Franjas y actualizar tiempo esperado
            $puntosFranjaABM = new ABM('tiempo_por_franja_por_punto');
            $franjaJoin      = array(
                'franjas' => array('tiempo_por_franja_por_punto.fkfranja' => 'franjas.idfranja')
            );
            $puntosFranjaAux = $puntosFranjaABM->getWithJoin(array('fkpunto_por_ruta' => array_keys($puntosPorRuta)), $franjaJoin, false, false, false);
            if (!empty($puntosFranjaAux))
            {
                $puntosFranja = array();
                foreach($puntosFranjaAux as $punto)
                {
                    $puntosFranja[$punto['fkpunto_por_ruta']][] = $punto;
                }
            }
            $ultimoPuntoId = 0;
            // Dia timestamp
            $diaTimestamp = mktime(0,0,0,date('m', $fechaSalida), date('d', $fechaSalida), date('y', $fechaSalida));
            // Recorrer puntos
            foreach ($puntosPorRuta as $idPunto => $puntoPorRuta)
            {
                // Limpiar punto
                $auxPunto = $puntoPorRuta;
                $puntoPorRuta = array();
                // Preparar punto
                $puntoPorRuta['idpunto_por_ruta'] = $auxPunto['idpunto_por_ruta'];
                $puntoPorRuta['nombre']           = $auxPunto['nombre'];
                $puntoPorRuta['tiempo_original']  = $auxPunto['segundos_anterior'];
                // Segundos esperados para puntos que no sean el de salida
                if ($auxPunto['orden'] > 0)
                {
                    // Tiene posibles franjas
                    if (!empty($puntosFranja[$idPunto]))
                    {
                        // Hay lectura de este punto
                        if (!empty($auxPunto['geolocalizaciones.fecha_timestamp']))
                        {
                            $auxDiaTimestamp     = mktime(0,0,0,date('m', $auxPunto['geolocalizaciones.fecha_timestamp']), date('d', $auxPunto['geolocalizaciones.fecha_timestamp']), date('y', $auxPunto['geolocalizaciones.fecha_timestamp']));
                            $auxLecturaTimestamp = $auxPunto['geolocalizaciones.fecha_timestamp'];
                        }
                        // No hay lectura de este punto
                        else
                        {
                            if (isset($puntosPorRuta[$idPunto]['lectura_esperada']))
                            {
                                $auxDiaTimestamp     = mktime(0,0,0,date('m', $puntosPorRuta[$idPunto]['lectura_esperada']), date('d', $puntosPorRuta[$idPunto]['lectura_esperada']), date('y', $puntosPorRuta[$idPunto]['lectura_esperada']));
                                $auxLecturaTimestamp = $puntosPorRuta[$idPunto]['lectura_esperada'];
                            }
                            else
                            {
                                $auxDiaTimestamp     = $diaTimestamp;
                                $auxLecturaTimestamp = $fechaSalida;
                            }
                        }
                        // Tiempo segun franja necesario?
                        $diaSemana = date('N', $auxLecturaTimestamp);
                        switch($diaSemana)
                        {
                            case '1': $bitmap = BITMAP_LUNES; break;
                            case '2': $bitmap = BITMAP_MARTES; break;
                            case '3': $bitmap = BITMAP_MIERCOLES; break;
                            case '4': $bitmap = BITMAP_JUEVES; break;
                            case '5': $bitmap = BITMAP_VIERNES; break;
                            case '6': $bitmap = BITMAP_SABADO; break;
                            case '7': $bitmap = BITMAP_DOMINGO; break;
                        }
                        foreach ($puntosFranja[$idPunto] as $franja)
                        {
                            if (($franja['dias'] & $bitmap) > 0)
                            {
                                $auxHorarioLectura  = $auxLecturaTimestamp - $auxDiaTimestamp;
                                if (($auxHorarioLectura >= $franja['horario_desde']) && ($auxHorarioLectura <= $franja['horario_hasta']))
                                {
                                    $tiempoEsperado = $franja['segundos_anterior'];
                                }
                            }
                        }
                    }
                    else
                    {
                        $tiempoEsperado = $auxPunto['segundos_anterior'];
                    }
                }
                else
                {
                    $tiempoEsperado = 0;
                }
                $puntoPorRuta['tiempo_esperado'] = $tiempoEsperado;
                // Asignar tiempos de llegada y esperados
                if (!empty($auxPunto['geolocalizaciones.fecha_timestamp']))
                {
                    if ($auxPunto['orden'] == 0)
                    {
                        $puntoPorRuta['timestamp_esperado'] = $salidaEsperada;
                    }
                    else
                    {
                        if (!empty($puntosPorRuta[$ultimoPuntoId]['timestamp_lectura']))
                        {
                            $puntoPorRuta['timestamp_esperado'] = $puntosPorRuta[$ultimoPuntoId]['timestamp_lectura'] + $puntoPorRuta['tiempo_esperado'];
                        }
                        else
                        {
                            $puntoPorRuta['timestamp_esperado'] = $puntosPorRuta[$ultimoPuntoId]['timestamp_esperado'] + $puntoPorRuta['tiempo_esperado'];
                        }
                    }
                    $puntoPorRuta['timestamp_lectura'] = $auxPunto['geolocalizaciones.fecha_timestamp'];
                    $puntoPorRuta['timestamp_proximo'] = $auxPunto['geolocalizaciones.proximo_punto_timestamp'];
                    $puntoPorRuta['alerta_desvio']     = false;
                }
                else
                {
                    if (!empty($puntosPorRuta[$ultimoPuntoId]['timestamp_lectura']))
                    {
                        $puntoPorRuta['timestamp_esperado'] = $puntosPorRuta[$ultimoPuntoId]['timestamp_lectura'] + $puntoPorRuta['tiempo_esperado'];
                    }
                    else
                    {
                        $puntoPorRuta['timestamp_esperado'] = $puntosPorRuta[$ultimoPuntoId]['timestamp_esperado'] + $puntoPorRuta['tiempo_esperado'];
                    }
                    $puntoPorRuta['timestamp_lectura'] = false;
                    $puntoPorRuta['timestamp_proximo'] = false;
                    $puntoPorRuta['alerta_desvio']     = true;
                }
                // Determinar si el movil sufrio un atraso
                if (!$puntoPorRuta['alerta_desvio'])
                {
                    if ($auxPunto['orden'] > 0)
                    {
                        $puntoPorRuta['tolerancia'] = ceil($puntoPorRuta['tiempo_esperado'] * TOLERANCIA_PORCENTAJE);
                    }
                    else
                    {
                        $puntoPorRuta['tolerancia'] = TOLERANCIA_SALIDA;
                    }
                    $diferencia = $puntoPorRuta['timestamp_esperado'] - $puntoPorRuta['timestamp_lectura'];
                    $absDif = (abs($diferencia)) + $puntoPorRuta['tiempo_esperado'];
					if (($absDif >= ($puntoPorRuta['tiempo_esperado'] - $puntoPorRuta['tolerancia'])) && ($absDif <= ($puntoPorRuta['tiempo_esperado'] + $puntoPorRuta['tolerancia'])))
					{
						$puntoPorRuta['alerta_tiempo'] = false;
                        $puntoPorRuta['diferencia']    = $diferencia;
					}
					else
					{
						$puntoPorRuta['alerta_tiempo'] = true;
                        $puntoPorRuta['diferencia']    = $diferencia;
					}
                }
                else
                {
                    $puntoPorRuta['tolerancia']         = false;
                    $puntoPorRuta['alerta_tiempo']      = false;
                    $puntoPorRuta['alerta_tiempo_cant'] = false;
                }
                // Asignar cosas
                $puntosPorRuta[$idPunto] = $puntoPorRuta;
                $ultimoPuntoId = $idPunto;
            }
            return $puntosPorRuta;
        }
        else
        {
            return false;
        }
    }

    public function getVehiculo($id)
    {
        $vehiculosAbm = new ABM('vehiculos');
        return $vehiculosAbm->get(array('idvehiculo' => $id, 'status' => STATUS_ONLINE));
    }

    public function getVehiculos()
    {
        $vehiculosAbm = new ABM('vehiculos');
        return $vehiculosAbm->get(array('status' => STATUS_ONLINE), array('nombre ASC'));
    }

    public function getGrupo($id)
    {
        $gruposAbm = new ABM('grupos');
        return $gruposAbm->get(array('idgrupo' => $id, 'status' => STATUS_ONLINE));
    }

    public function getGrupos()
    {
        $gruposAbm = new ABM('grupos');
        return $gruposAbm->get(array('status' => STATUS_ONLINE), array('nombre ASC'));
    }

}
?>